/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.core.service.impl;

import com.google.common.collect.Lists;
import com.intelligent.ispc.common.mapper.BeanMapper;
import com.intelligent.ispc.common.persistence.DynamicSpecifications;
import com.intelligent.ispc.common.persistence.SearchFilter;
import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ApplicationUtil;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.common.utils.FileUtils;
import com.intelligent.ispc.core.dto.ExportFileDto;
import com.intelligent.ispc.core.dto.RoleDto;
import com.intelligent.ispc.core.dto.SecurityUserDto;
import com.intelligent.ispc.core.entity.ExportFile;
import com.intelligent.ispc.core.repository.jpa.ExportFileDao;
import com.intelligent.ispc.core.repository.jpa.UserDao;
import com.intelligent.ispc.core.service.ExportFileService;
import com.intelligent.ispc.utils.ExportFileStatus;
import com.intelligent.ispc.utils.SystemConfig;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by Peter on 15/11/23.
 */
@Service
public class ExportFileServiceImpl implements ExportFileService {

    private Logger logger = LoggerFactory.getLogger(ExportFileServiceImpl.class);

    @Autowired
    private ExportFileDao exportFileDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private SystemConfig systemConfig;

    @Override
    public Long createExportFile(ExportFileDto exportFileDto) {
        if (exportFileDto == null || exportFileDto.getProjectName() == null || exportFileDto.getCreateBy() == null) {
            throw new ApplicationException(ExceptionMessages.EXCEPTION_PARAMETER_INPUT_INVALID);
        }

        ExportFile entity = new ExportFile();
        BeanMapper.copy(exportFileDto, entity);
        exportFileDao.save(entity);

        return entity.getId();
    }

    @Override
    public void updateExportFileStatus(Long id, ExportFileStatus status) {
        if (id == null || status == null) {
            throw new ApplicationException(ExceptionMessages.EXCEPTION_PARAMETER_INPUT_INVALID);
        }

        ExportFile entity = exportFileDao.findById(id);

        if (entity == null) {
            throw new ApplicationException(ExceptionMessages.EXCEPTION_OBJECT_DOES_NOT_EXIST);
        }
        entity.setStatus(status);

        exportFileDao.save(entity);
    }

    @Override
    public void deleteExportFile(Long id) {
        if (id == null) {
            throw new ApplicationException(ExceptionMessages.EXCEPTION_PARAMETER_INPUT_INVALID);
        }

        ExportFile entity = exportFileDao.findById(id);

        Subject subject = SecurityUtils.getSubject();
        SecurityUserDto userDto = (SecurityUserDto) subject.getPrincipal();
        String loginName = userDto.getLoginName();

        List<RoleDto> roles = userDto.getRoles();
        boolean isAdmin = false;
        for (RoleDto roleDto : roles) {
            if ("Administrator".equalsIgnoreCase(roleDto.getName())) {
                isAdmin = true;
                break;
            }
        }
        if (!isAdmin) {
            if (!entity.getCreateBy().equalsIgnoreCase(loginName)) {
                throw new ApplicationException(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
        }

        exportFileDao.delete(entity);

        String fileName = entity.getUrl();
        fileName = fileName.substring(fileName.lastIndexOf("/") + 1, fileName.length());
        FileUtils.deleteFile(ApplicationUtil.getProjectPathWithSeparator() + "exports" + ApplicationUtil.getFileSeparator() + fileName);
    }

    @Override
    public List<ExportFileDto> searchFile(Map<String, Object> searchParams) {
        SecurityUserDto userDto = (SecurityUserDto) SecurityUtils.getSubject().getPrincipal();
        List<ExportFileDto> exportFileDtos = Lists.newArrayList();

        Iterable<ExportFile> fileList = exportFileDao.findAll(new Sort(Sort.Direction.DESC, "createTime"));
        Iterator iter = fileList.iterator();
        while (iter.hasNext()) {
            ExportFile entity = (ExportFile) iter.next();
            ExportFileDto dto = new ExportFileDto();
            BeanMapper.copy(entity, dto);
            exportFileDtos.add(dto);
        }
        return exportFileDtos;
    }

    @Override
    public Page<ExportFileDto> searchFile(Map<String, Object> searchParams, Pageable pageable) {
        logger.debug("Searching user with {},{},{}", searchParams.keySet(), searchParams.values(), pageable);

        Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
        Specification<ExportFile> spec = DynamicSpecifications.bySearchFilter(filters.values(), ExportFile.class);

        Page<ExportFile> exportFilesPage = exportFileDao.findAll(spec, pageable);
        logger.debug("Searching project, total elements:{}", exportFilesPage.getTotalElements());

        List<ExportFile> files = exportFilesPage.getContent();
        List<ExportFileDto> exportFileDtos = Lists.newArrayList();
        for (ExportFile entity : files) {
            ExportFileDto dto = new ExportFileDto();
            BeanMapper.copy(entity, dto);
            exportFileDtos.add(dto);
        }

        Page<ExportFileDto> pageDto = new PageImpl<ExportFileDto>(exportFileDtos, pageable, exportFilesPage.getTotalElements());

        return pageDto;
    }
}
